package cc.rengu.redp.flowable.bizmodel.web.service.impl;

import cc.rengu.redp.common.domain.QueryRequest;
import cc.rengu.redp.common.utils.SortUtil;
import cc.rengu.redp.flowable.bizmodel.metadata.ModelHandler;
import cc.rengu.redp.flowable.bizmodel.db.dao.BizCfgModelMapper;
import cc.rengu.redp.flowable.bizmodel.db.domain.BizCfgAlg;
import cc.rengu.redp.flowable.bizmodel.db.domain.BizCfgField;
import cc.rengu.redp.flowable.bizmodel.db.domain.BizCfgModel;
import cc.rengu.redp.flowable.bizmodel.web.service.BizCfgAlgService;
import cc.rengu.redp.flowable.bizmodel.web.service.BizCfgFieldService;
import cc.rengu.redp.flowable.bizmodel.web.service.BizCfgModelService;
import cc.rengu.redp.flowable.service.SysWorkFlowService;
import cc.rengu.redp.system.domain.User;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.repository.ProcessDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author xushitang
 */
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class BizCfgModelServiceImpl extends ServiceImpl<BizCfgModelMapper, BizCfgModel> implements BizCfgModelService {

    @Autowired
    private BizCfgAlgService bizCfgAlgService;
    @Autowired
    private BizCfgFieldService bizCfgFieldService;
    @Autowired
    private SysWorkFlowService sysWorkFlowService;
    @Autowired
    private ModelHandler modelHandler;

    @Override
    public IPage<BizCfgModel> findBizCfgModel(QueryRequest request, BizCfgModel bizCfgModel) {
        try {
            LambdaQueryWrapper<BizCfgModel> queryWrapper = new LambdaQueryWrapper<>();

            if (StringUtils.isNotBlank(bizCfgModel.getModelName())) {
                queryWrapper.like(BizCfgModel::getModelName, bizCfgModel.getModelName());
            }
            Page<BizCfgModel> page = new Page<>();
            SortUtil.handlePageSort(request, page, true);
            return this.page(page, queryWrapper);
        } catch (Exception e) {
            log.error("获取字典信息失败", e);
            return null;
        }
    }

    @Override
    public List<BizCfgModel> findAllAvailableModels(User user) {
        LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper();
        List<BizCfgModel> bizCfgModels = this.baseMapper.selectList(lambdaQueryWrapper);
        Iterator<BizCfgModel> it = bizCfgModels.iterator();
        while (it.hasNext()){
            if (!modelHandler.modelAuth(it.next(), user)){
                it.remove();
            }
        }
        return bizCfgModels;
    }

    @Override
    public List<BizCfgField> findIndexedFieldsInModel(String modelId) {
        LambdaQueryWrapper<BizCfgField> lqw = new LambdaQueryWrapper();
        lqw.eq(BizCfgField::getModelId, Long.valueOf(modelId)).eq(BizCfgField::getIsIndex, true);
        return bizCfgFieldService.list(lqw);
    }

    @Override
    public List<BizCfgField> findFieldsInModel(String modelId) {
        LambdaQueryWrapper<BizCfgField> lqw = new LambdaQueryWrapper();
        lqw.eq(BizCfgField::getModelId, Long.valueOf(modelId));
        List<BizCfgField> bizCfgFields = bizCfgFieldService.list(lqw);
        Iterator<BizCfgField> it = bizCfgFields.iterator();
        while (it.hasNext()) {
            BizCfgField bizCfgField = it.next();
            if ("Array".equals(bizCfgField.getFieldType())) {
                it.remove();
            } else if (StringUtils.isNotBlank(bizCfgField.getFatherFieldName())){
                it.remove();
            }
        }
        return bizCfgFields;
    }

    @Override
    public void saveBizCfgModel(BizCfgModel bizCfgModel, List<BizCfgField> bizCfgFields) {
        if (bizCfgModel.getModelId() == null || bizCfgModel.getModelId() < 0) {
            //新增模型（先save模型，获得modelID）
            bizCfgModel.setModelId(null);
            this.save(bizCfgModel);
            //新增算法和字段
            bizCfgFields.forEach(fieldItem -> {
                fieldItem.setModelId(bizCfgModel.getModelId());
                bizCfgFieldService.save(fieldItem);
                fieldItem.getAlgData().forEach(algItem ->{
                    algItem.setFieldId(fieldItem.getFieldId());
                    bizCfgAlgService.save(algItem);
                });
            });
        } else {
            //删除算法
            bizCfgFields.forEach(fieldItem -> {
                LambdaQueryWrapper<BizCfgAlg> lqwAlg = new LambdaQueryWrapper<>();
                lqwAlg.eq(BizCfgAlg::getFieldId, fieldItem.getFieldId());
                bizCfgAlgService.remove(lqwAlg);
            });

            //删除字段
            LambdaQueryWrapper<BizCfgField> lqwField = new LambdaQueryWrapper<>();
            lqwField.eq(BizCfgField::getModelId, bizCfgModel.getModelId());
            bizCfgFieldService.remove(lqwField);

            //新增算法和字段
            bizCfgFields.forEach(fieldItem -> {
                fieldItem.setModelId(bizCfgModel.getModelId());
                bizCfgFieldService.save(fieldItem);
                fieldItem.getAlgData().forEach(algItem ->{
                    algItem.setFieldId(fieldItem.getFieldId());
                    bizCfgAlgService.save(algItem);
                });
            });

            //更新模型
            this.updateById(bizCfgModel);
        }

    }

    @Override
    public void deleteBizCfgModel(String[] modelIds) {
        for (String modelId : modelIds) {
            //获取字段集合
            LambdaQueryWrapper<BizCfgField> fieldWrapper = new LambdaQueryWrapper<>();
            fieldWrapper.eq(BizCfgField::getModelId, modelId);
            List<BizCfgField> bizCfgFields = bizCfgFieldService.list(fieldWrapper);
            //删除字段
            List<Long> fieldIds = bizCfgFields.stream().map(BizCfgField::getFieldId).collect(Collectors.toList());
            bizCfgFieldService.removeByIds(fieldIds);
            //删除算法
            bizCfgFields.forEach(fieldItem -> {
                LambdaQueryWrapper<BizCfgAlg> lqwAlg = new LambdaQueryWrapper<>();
                lqwAlg.eq(BizCfgAlg::getFieldId, fieldItem.getFieldId());
                bizCfgAlgService.remove(lqwAlg);
            });
        }
        //删除模型
        this.baseMapper.deleteBatchIds(Arrays.asList(modelIds));
    }

    @Override
    public Map<String, Object> getBizCfgModel(String modelId) {
        Map<String, Object> rs = new HashMap<>();
        BizCfgModel bizCfgModel = this.baseMapper.selectById(modelId);
        //获取字段集合
        LambdaQueryWrapper<BizCfgField> fieldWrapper = new LambdaQueryWrapper<>();
        fieldWrapper.eq(BizCfgField::getModelId, bizCfgModel.getModelId());
        List<BizCfgField> bizCfgFields = bizCfgFieldService.list(fieldWrapper);
        //对字段集合进行加工处理
        for (int voFieldKey = 0; voFieldKey < bizCfgFields.size(); voFieldKey++){
            BizCfgField bizCfgField = bizCfgFields.get(voFieldKey);
            //获取字段下的算法集合
            LambdaQueryWrapper<BizCfgAlg> algWrapper = new LambdaQueryWrapper<>();
            algWrapper.eq(BizCfgAlg::getFieldId, bizCfgField.getFieldId());
            List<BizCfgAlg> bizCfgAlgs = bizCfgAlgService.list(algWrapper);
            for (int voAlgKey = 0; voAlgKey < bizCfgAlgs.size(); voAlgKey++){
                //设置算法序号
                bizCfgAlgs.get(voAlgKey).setKey(voAlgKey);
            }
            //设置字段序号
            bizCfgField.setKey(voFieldKey);
            //设置字段算法集合
            bizCfgField.setAlgData(bizCfgAlgs);
            //设置算法统计总数
            bizCfgField.setAlgCount(bizCfgAlgs.size());
        }

        rs.put("bizCfgModel", bizCfgModel);
        rs.put("fieldData", bizCfgFields);
        return rs;
    }

    @Override
    public Map<String, String> getAllProcesses() {
        Map<String, String> allProcesses = new HashMap<>();
        List<ProcessDefinition> procDefs = sysWorkFlowService.getAllProcesses();
        procDefs.forEach(pd -> allProcesses.put(pd.getKey(), pd.getName()));
        return allProcesses;
    }

    @Override
    public Map<String, String> getEndEvents(String procDefId) {
        return sysWorkFlowService.getEndEventsByProcDefId(procDefId);
    }
}
